package com.mojo.elastic.controller;

import com.mojo.elastic.pojo.Log;
import com.mojo.elastic.pojo.UserCompanyAssigned;
import com.mojo.elastic.repository.LogRepository;
import com.mojo.elastic.service.LogService;
import com.mojo.response.ResultListVO;
import com.mojo.response.ResultVO;
import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
import org.elasticsearch.index.query.*;
import org.elasticsearch.search.aggregations.Aggregations;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.elasticsearch.core.ElasticsearchOperations;
import org.springframework.data.elasticsearch.core.IndexOperations;
import org.springframework.data.elasticsearch.core.SearchHits;
import org.springframework.data.elasticsearch.core.document.Document;
import org.springframework.data.elasticsearch.core.query.NativeSearchQuery;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.web.bind.annotation.*;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

/**
 * es
 * <p>
 * spring data elasticsearch查询步骤
 * 1、声明是什么查询,组装查询条件
 * 2、build查询对象NativeSearchQuery实例对象
 * 3、ElasticsearchOperations调用方法执行查询
 *
 * @author <a href="mailto:sjj@jianzhimao.com">mojo</a>
 * copyright (C), 2013-2022, 广州九尾信息科技有限公司
 * @date 2022/4/22 15:08
 */
@RestController
@RequestMapping("es")
public class ESController {
    private static final Logger logger = LoggerFactory.getLogger(ESController.class);
    @Autowired
    private LogRepository logRepository;
    @Autowired
    private LogService logService;
    @Autowired
    private ElasticsearchOperations elasticsearchOperations;

    @GetMapping("log/{id}")
    public Log getLog(@PathVariable("id") Integer id) {
        Optional<Log> optional = logRepository.findById(id);

        return optional.get();
    }

    @PutMapping("log")
    public ResultVO<Log> editLog(@RequestBody Log log) {
        Log log1 = logRepository.save(log);
        return new ResultVO<>(log1);

    }

    @DeleteMapping("log/{id}")
    public void deleteLog(@PathVariable("id") Integer id) {

    }

    public void esComposition() {

    }

    /**
     * 布尔查询
     */
    @GetMapping("bool")
    void bool() {
        logService.boolQuery();

    }

    /**
     * 删除索引
     *
     * @param index 索引名称
     * @author Mojo
     */
    public void deleteIndex(String index) {
        DeleteIndexRequest request = new DeleteIndexRequest();

    }

    /**
     * 创建索引log
     */
    @PutMapping("/index/log")
    public void createIndex() {
        IndexOperations indexOps = elasticsearchOperations.indexOps(Log.class);
        if (indexOps.exists()) {
            // 删除索引
            elasticsearchOperations.indexOps(Log.class).delete();
        }
        elasticsearchOperations.indexOps(Log.class).create();
        Document mapping = elasticsearchOperations.indexOps(Log.class).createMapping();
        boolean flag = elasticsearchOperations.indexOps(Log.class).putMapping(mapping);
        logger.info("创建mapping结果：{}", flag);
    }

    /**
     * term关键字查询
     */
    @GetMapping("/consumer")
    public void termQuery() {
        // 1、声明是什么查询,组装查询条件
        // 关键字查询
        TermQueryBuilder termQuery = QueryBuilders.termQuery("name", "mojo");
        // 布尔查询
        BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
        boolQuery.must(termQuery);
        boolQuery.should(QueryBuilders.termQuery("age", 11));
        boolQuery.should(QueryBuilders.termQuery("age", 22));
        boolQuery.minimumShouldMatch();
        // 范围查询
        RangeQueryBuilder rangeQuery = QueryBuilders.rangeQuery("age");
        rangeQuery.gte(11);

        // 2、构建NativeSearchQuery
        NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();
        queryBuilder.withQuery(termQuery);
        queryBuilder.withQuery(boolQuery);
        queryBuilder.withQuery(rangeQuery);
        NativeSearchQuery query = queryBuilder.build();
        // 3.调用search方法
        SearchHits<Log> hits = elasticsearchOperations.search(query, Log.class);
        Aggregations aggregations = hits.getAggregations();
    }

    /**
     * terms查询
     * <p>
     * terms查询类似term查询，不过terms查询是一个字段有多个查询参数
     * term: where name=mojo
     * terms where name=mojo or name=jj
     *
     * @return void
     */
    @GetMapping("/terms")
    public ResultListVO<UserCompanyAssigned> termsQuery() {
        TermsQueryBuilder termsQuery = QueryBuilders.termsQuery("name", "mojo", "jj");
        NativeSearchQueryBuilder builder = new NativeSearchQueryBuilder();
        builder.withQuery(termsQuery);
        NativeSearchQuery query = builder.build();
        SearchHits<UserCompanyAssigned> searchHits = elasticsearchOperations.search(query, UserCompanyAssigned.class);
        return new ResultListVO<>();
    }

    /**
     * match查询属于高级查询，他会根据你查询的字段类型不一样，采用不同的查询方式,更加灵活多变
     * <p>match查询，实际底层就是多个term查询，将多个term查询的结果封装到一起
     * <pre>
     * 如果查询的是日期或者是数值的话，他会将你基于的字符串查询内容转换为日期或者数值对待。
     * 如果查询的内容是一个不能被分词的内容（keyword），match查询不会对你指定的查询关键字进行分词。
     * 如果查询的内容时一个可以被分词的内容（text），match会将你指定的查询内容根据一定的方式去分词，去分词库中匹配指定的内容。
     * <pre/>
     */
    @GetMapping("/match")
    public void match() {
        MatchQueryBuilder matchQuery = QueryBuilders.matchQuery("name", "mojo");
        NativeSearchQueryBuilder builder = new NativeSearchQueryBuilder();
        builder.withQuery(matchQuery);
        NativeSearchQuery query = builder.build();
        SearchHits<UserCompanyAssigned> searchHits = elasticsearchOperations.search(query, UserCompanyAssigned.class);

    }

    /**
     * matchAll查询
     */
    public void matchAll() {
        MatchAllQueryBuilder matchAllQuery = QueryBuilders.matchAllQuery();
        NativeSearchQueryBuilder builder = new NativeSearchQueryBuilder();
        builder.withQuery(matchAllQuery);
        NativeSearchQuery query = builder.build();
        SearchHits<UserCompanyAssigned> searchHits = elasticsearchOperations.search(query, UserCompanyAssigned.class);
    }

    public void multiMatch() {
        MultiMatchQueryBuilder multiMatchQuery = QueryBuilders.multiMatchQuery("科技信息有限公司", "content", "mark");
        NativeSearchQueryBuilder builder = new NativeSearchQueryBuilder();
        builder.withQuery(multiMatchQuery);
        builder.build();
    }

    /**
     * 模糊查询
     */
    public void fuzzy() {
        FuzzyQueryBuilder fuzzyQuery = QueryBuilders.fuzzyQuery("content", "科技有限公司");
        // 指定前面n个字符需精确匹配
        fuzzyQuery.prefixLength(2);
        NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();
        queryBuilder.withQuery(fuzzyQuery);
        NativeSearchQuery query = queryBuilder.build();
        SearchHits<UserCompanyAssigned> searchHits = elasticsearchOperations.search(query, UserCompanyAssigned.class);
    }

    /**
     * 统配查询，类似mysql中的like查询
     */
    public void wildSearch() {
        // 使用通配符构建查询条件对象，可以使用*和?指定通配符和占位符
        WildcardQueryBuilder wildcardQuery = QueryBuilders.wildcardQuery("content", "科技有限公司*");

    }

    /**
     * 范围查询
     */
    public void range() {
        RangeQueryBuilder rangeQuery = QueryBuilders.rangeQuery("id");

    }
    // =================================================================================================================

    /**
     * 提高查询
     */
    void boosting() {

    }

    /**
     * 固定分数查询
     */
    void constantScore() {

    }

    /**
     * 最佳匹配查询
     */
    void disMax() {

    }

    /**
     * 函数查询
     */
    void functionScore() {

    }

    @PutMapping("/consumer")
    public ResultVO<List<Log>> save() {
        Log log = new Log();
        log.setName("mojo");
        log.setAge(11);
        List<Log> list = new ArrayList<>();
        list.add(log);
        List<Log> result = (List<Log>) elasticsearchOperations.save(list);
        return new ResultVO<>(result);
    }

}



